feat(amf): add native AMD AMF encoder - #342
Conversation
|
I've quickly tested the latest build and the streaming got broken on AV1/HEVC/H264. The interesting thing is that Artemis told me my GPU wasn't capable of HDR when I started the stream. I only got a purple screen when the stream started. Sorry for not providing the log but I couldn't since I was in a hurry. |
|
@RunAway189 Thanks for testing and reporting, that's exactly the kind of report that's useful even without a log. I tried to reproduce on an RX 7900 XT (AMF 1.5.2.0, Moonlight 6.1.0, 1080p120 @ 50 Mbps) and could not. What passed here on the current head: AV1, HEVC and H.264 in SDR, plus AV1 and HEVC with HDR actually negotiated ( What would help most, in rough order:
Also useful as a bisect: the previous tester build is still up with the same install steps, native-amf-stable2-20260723. If that one streams fine and the newest doesn't, that narrows it to a handful of commits and I'll find it quickly. If both are broken the same way, it's not from the recent changes and the log becomes the fastest path. One thing your report already earned regardless: reviewing the newest changes under suspicion turned up a real latent bug of my own, a dropped submission could withhold the frame counter and, under conditions that persist, freeze the stream instead of just skipping a frame. That's reverted on the branch now. |
|
This issue you have could also be related to my separate VDD PR. |
Adds a native AMD AMF encoder for Windows using D3D11 zero-copy input, replacing the FFmpeg-based path for `amdvce`. H.264, HEVC and AV1 are supported, with SDR/HDR where the selected driver mode allows, dynamic bitrate, IDR and reference-frame invalidation, bounded queue and backpressure handling, and ordered startup and teardown. `amdvce` selects the native encoder. `amdvce_legacy` remains as an explicit rollback and is exposed in the encoder dropdown and the docs; automatic probing never silently falls back to it, and an explicit `amdvce` selection fails closed rather than changing implementations behind the user. Design contracts: - Every requested AMF property is set and read back. A rejected or post-Init-drifted value fails encoder creation instead of silently streaming a different configuration. The client reference-frame limit and the H.264 intra-refresh two-reference floor come from one shared helper used identically at configure time and at verification, so the encoder cannot reject its own raise. - Only AMF_INPUT_FULL and AMF_DECODER_NO_FREE_SURFACES retry a submission. AMF_NEED_MORE_INPUT means the input was consumed and output is deferred, which is what PreAnalysis returns while priming, so the surface is never resubmitted. - Submit retries, the input ring, the surface pool, and both the teardown fence and the driver-destruction watchdog are individually bounded. A wedged driver quarantines native AMF for the host's lifetime instead of hanging the process. - Runtime fatals (TDR, sustained backpressure, output stalls) rebuild the same native session, bounded to three attempts, and stay fail-closed while quarantined. - Input-surface reservations are generation-tagged, so a driver-delayed release callback cannot recycle a surface the VCN may still be reading. - Bitstream extraction and input-pool allocation run outside the encoder state lock, the output pump waits interruptibly rather than sleeping in fixed quanta, and the encode loop performs one RTTI lookup per session rather than per frame. - Split-frame encoding is enabled on HEVC and AV1 only where the GPU reports more than one VCN instance; it has no user-facing knob. Xbox intra-refresh honors `enableIntraRefresh == 1` on a 300-frame cycle: H.264 refreshes 16x16 macroblocks and HEVC 64x64 CTBs across 299 refresh frames, AV1 uses continuous mode, and H.264 avoids conflicting LTR configuration. Requested properties are read back, so driver rejection fails the session rather than silently ignoring the request. The AMD settings surface is limited to choices a user can reason about: usage, rate control, QVBR level, quality preset, VBAQ, PreAnalysis, HRD, H.264 coder, and the AV1 content and latency modes. Driver internals that the encoder already resolves correctly are not exposed. Signed-off-by: Ramazan Kara <github@r-kara.de>
cc9bbf5 to
01b7a64
Compare
|
From my side this is stable enough to be worth a review, so I would like to hand it over for your input on the approach and the scope before it goes any further. I am stopping active work on it here. Development on main moves quickly enough that keeping this branch rebased and re-measured against it has become most of the effort, and someone closer to main is better placed to carry it from this point. State of things: everything is one commit against |
Hi, I've just tested the latest one and I got the same results. I'm going to attach the debug log and answer to your questions:
Here's the log: |
|
Found it in the log, thanks for the debug capture. Every SDR probe succeeds and every 10-bit HDR probe fails: Error 10 is The trigger is PreAnalysis combined with 10-bit. Your config has Set rate control to I guess we could automatically set the encoder to drop PreAnalysis on 10-bit sessions instead of failing init and losing HDR entirely. I have stopped active work on this branch, so I am leaving that to whoever picks it up, and this comment is here so the cause is on record. When the next stable version is merged, I might rebase and also include this. |
There was a lot of refactoring work done by Terra Ultra to fix longstanding issues, but at this point I can maintain the code from here. I will handle the bug fixes and security issues from here. I appreciate you spending the time to do this for AMD users. As for everyone else, if you notice an AMD specific problem please open an issue up with logs and I will take over the bug fixes from here. |
PR #342 renamed the FFmpeg-based AMD encoder to "amdvce_legacy" and gave the name "amdvce" to the new native AMF encoder. Vibeshine's Radeon Pro 5500 XT Main10 workaround was still gated on encoder.name == "amdvce" inside make_avcodec_encode_session, which native amdvce never reaches: it is built on encoder_platform_formats_amf, so the encoder_platform_formats_avcodec dynamic_cast at the top of that function returns nullptr first. The workaround became dead code, and the encoder that actually needs it -- amdvce_legacy, the documented rollback -- never got it. Point the check at amdvce_legacy and say so in the docs, which still claimed the exception applies automatically without naming the encoder. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019n87Soo2y8hXqUa764ModC (cherry picked from commit beeb8e62dbfcb6b36b2b24ebb9b0aa2350ee8417)
I've just tested and confirmed your theory: leaving vbr_latency and AMF PreAnalysis off fixed my streaming issue. The HDR is back and everything is as smooth as always. That said, in my opinion the new modes — QVBR, HQVBR, and HQCBR — offer better image quality compared to vbr_latency. I don't know which of you will be handling this issue, but if you need any further tests to fix it, just let me know. I'll be here to help both of you, @RamazanKara @Nonary. Also, I tried streaming without HDR for the first time on my Odin 2 Portal, and what surprised me the most was how much clearer the text looked on Windows. I'm not sure why, but when HDR is enabled, all the text seems to have a white outline, making everything look "blurrier" and less crisp than when HDR is off. I don't know if that makes sense, but that's what I found. It happens both with this test version and the official Vibepollo build. |
|
Thanks for the substantial work on the native AMD AMF encoder. This is a friendly provenance reminder, not a challenge to Vibepollo’s right to reuse the code. We understand that both Foundation Sunshine and Vibepollo are released under GPLv3, and that GPLv3 permits copying, modification, and redistribution under its terms. During our review, we noticed that several additions in: src/amf/amf_d3d11.cpp closely match the earlier AlkaidLab/foundation-sunshine@3340d28 This includes the LOWLATENCY_MODE / INPUT_QUEUE_SIZE changes, the related rationale comments, and the reference to AlkaidLab/foundation-sunshine#666. That Foundation commit predates this PR. The current PR description says “Based on 1.18.3-beta.2”, but does not mention the Foundation implementation or commit as a source. Since both projects are GPLv3-licensed, we are not disputing the legality of reusing the code. We are only asking for the provenance to be made clear and for any applicable copyright, license, and modification notices to remain preserved. If these parts were derived from Foundation, could you please update the PR or commit documentation with a source reference such as: Based on AlkaidLab/foundation-sunshine commit 3340d28 (ClassicOldSong#666), modified for Vibepollo by Ramazan Kara, and released under GPLv3. If the implementation was developed independently, please clarify the common provenance and differences so that the contribution history remains accurate. Thanks for helping keep the licensing and contribution history clear. =========================== At the same time, this reminds us that AI still needs human guidance in this kind of work. Guiding and reviewing AI is not only a responsibility that developers have toward the community; it is also an acknowledgment of the community members who help test the software and report problems. We will continue maintaining the AMD-related functionality on our side. If we make any new discoveries in the future, we would be happy to share our experience and learn from each other. ===================== At the same time, this reminds us that AI still needs human guidance in this kind of work. Guiding and reviewing AI is not only a responsibility that developers have toward the community; it is also an acknowledgment of the community members who help test the software and report problems. We will continue maintaining the AMD-related functionality on our side. If we make any new discoveries in the future, we would be happy to share our experience and learn from each other. |
|
This is AI generated code, I can't prove it was taken from sunshine foundation or not. @RamazanKara would have to clarify that and if so, I will properly accredit the sourcing. |
|
@Yundi339 You are right, and thank you for raising it directly and with the specific commit. I checked rather than taking it on faith. Comparing 3340d28 against current master, 37 comment lines added by that commit appear verbatim in this tree: 25 in So to answer @Nonary directly: yes, those parts are derived from Foundation. The attribution should have been there from the start and its absence is on me as the submitter. I have opened #382, which adds a provenance notice to the header of both files naming the commit, the issue, qiin2333 as the author, and the GPLv3 license both projects share. If you would prefer different wording or want the notice placed at the specific call sites instead of the file headers, say so and I will change it. @Nonary when this reaches release notes, could Foundation Sunshine be credited for the AMD default handling, and could I be listed for the native encoder work alongside it? Foundation first, since that part predates mine. On your postscript: it is a fair point and this is a concrete instance of it. This work was produced with heavy AI assistance, and provenance is precisely the sort of thing that disappears when nobody stops to ask where a rationale comment came from. Reviewing output for correctness is not the same as reviewing it for origin, and I did the first and not the second. I appreciate you handling it as a reminder rather than an accusation, and the offer to share findings goes both ways. The HDR failure under PreAnalysis discussed earlier in this thread is one you may well hit on RDNA4 too. |
|
They’ve only requested that the copyright and license notices be preserved in the source files and that the GPL’s license obligations are followed. I don’t think crediting the original project in the release notes is necessary, and it would be excessive as a general practice. Many open source projects depend on GPL-licensed software, and release notes would quickly become an endless list of acknowledgements if that were expected. To me, release notes are primarily for informing users about changes and highlighting noteworthy contributions. Attribution to upstream projects is typically handled through the preserved copyright notices, license files, and other licensing requirements, unless the project is largely a fork or the maintainers have specifically requested additional acknowledgement. |
|
I’m here, I’m here, I just saw the emails 😂 You’re right, I should have clarified this earlier. |
|
@RamazanKara There is no need to explain it in the comments. That would just pollute the codebase. Unless we become good enough to publish an RFC specifically dedicated to AMD encoder handling. |
@RamazanKara Got it, if we run into this issue, we’ll take a look at it. For AMD, the situation on Honestly, AMD is a bit mysterious for developers. Even with AI assistance, different developers can have different understandings of how the AMD encoder behaves. A single AMD GPU is simply not enough to cover all the cases. Right now, we mainly rely on feedback from the community and gradually add fixes based on real-world reports. Especially because AMD keeps adding new features through driver updates, the AMD user base is split into different groups with different driver behaviors. For example, there was an HDR-related issue where users did not enable HDR, but the output was still overexposed. After investigation, we found that some AMD drivers enabled 10-bit output by default, so we added detection for that case. |
|
Done. The provenance note with the commit link is now in this PR's description, and I closed #382 since file headers were more than anyone asked for. Release-notes point withdrawn too, the preserved notices cover it. Buying a GPU just to chase community reports is dedication, hats off to qiin2333. If we hit anything new on the AMD side it will land in your tracker. |
Summary
Native AMD AMF encoder for Windows (D3D11 zero-copy), replacing the FFmpeg-based path for
amdvce. H.264, HEVC and AV1, with SDR/HDR where the selected driver mode allows, dynamic bitrate, IDR and reference-frame invalidation, bounded queue/backpressure handling, and ordered startup and teardown.Strictly AMD-scoped: encoder code, AMD configuration/UI/docs, build integration, and AMD-focused tests. Based on
1.18.3-beta.2.amdvceselects the native encoder.amdvce_legacyis the explicit rollback, exposed in the encoder dropdown and the docs. Automatic probing never silently falls back to it, and an explicitamdvceselection fails closed rather than changing implementations behind the user.Design contracts
AMF_INPUT_FULLandAMF_DECODER_NO_FREE_SURFACESretry a submission.AMF_NEED_MORE_INPUTmeans the input was consumed with output deferred — what PreAnalysis returns while priming — so the surface is never resubmitted.Xbox intra-refresh
enableIntraRefresh == 1follows a 300-frame cycle: H.264 refreshes 16×16 macroblocks and HEVC 64×64 CTBs across 299 refresh frames, AV1 uses continuous mode, and H.264 avoids conflicting LTR configuration. Clients that send a single reference, or no limit at all, receive the required two-reference floor. Properties are read back, so driver rejection fails the session rather than silently ignoring the request.Covered by unit tests. Desktop Moonlight does not send the Xbox request, so confirmation on real Xbox hardware is still welcome.
Quality presets
Autoleaves the property unset. Explicit presets are applied after usage and read back; a rejected or changed value fails the session instead of silently selecting a different preset.Validation
These were measured on commit
a7d54ff4of this branch. The subsequent changes were the1.18.3-beta.2merge and scope cleanup; nothing undersrc/amf/changed, so the figures remain representative, but they are not a run of the exact head.A tester build is available: native-amf-20260725 (unsigned; Windows may warn). Reports should include GPU, driver version, codec, HDR state, selected AMD settings, and reconnect behavior.
Provenance
The opt-in handling of
LOWLATENCY_MODE,INPUT_QUEUE_SIZEand the AV1 encoding latency mode, along with its rationale, derives from Foundation Sunshine: AlkaidLab/foundation-sunshine@3340d28 by qiin2333 (AlkaidLab/foundation-sunshine#666), adapted for Vibepollo. Both projects are GPLv3.